﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Windows.Media.Media3D;


namespace PlanetsAndOrbs
{
    class Planet : Sphere
    {
        Vector3D north_, equator1_, equator2_;
        Bitmap mapImage_;

        public Planet(Vector3D center, double radius, Bitmap mapImage, Random r)
            : base(center, radius)
        {
            mapImage_ = mapImage;

            // generate north vect
            north_ = new Vector3D(r.Next(100) - 5, r.Next(50), r.Next(100) - 50);
            north_.Normalize();

            // generate equator1
            do
            {
                equator1_ = new Vector3D(r.Next(100) - 50, r.Next(100) - 50, r.Next(100) - 50);
                double proj = Vector3D.DotProduct(north_, equator1_);
                equator1_ -= north_ * proj; // made it perpendicular to north
            }
            while(equator1_.LengthSquared == 0);
            equator1_.Normalize();

            equator2_ = - Vector3D.CrossProduct(equator1_, north_);
        }

        public override bool trace(ref Vector3D origin, ref Vector3D ray, out Vector3D filter, out Vector3D emission)
        {
            filter = new Vector3D();

            Vector3D normal = center_ - origin;
            normal.Normalize();

            int latitude = (int) (
                (mapImage_.Height - 1) * 
                (Math.Asin(Vector3D.DotProduct(normal, north_)) / Math.PI + 0.5)); 

            Vector3D radius = new Vector3D(Vector3D.DotProduct(normal, equator1_), Vector3D.DotProduct(normal, equator2_), 0);
            radius.Normalize();

            double a;
            if(Math.Abs(radius.X) < Math.Abs(radius.Y))
            {
                a = Math.Asin(radius.X) / Math.PI / 2;
                a = radius.Y < 0 ? 0.125 - a : 0.625 + a;
            }
            else 
            {
                a = Math.Asin(radius.Y) / Math.PI / 2;
                a = radius.X < 0 ? 0.375 + a : 0.875 - a;
            }
            int longitude = (int) ((mapImage_.Width - 1) * a);

            double alpha = Math.Abs(Vector3D.DotProduct(ray, normal));

            emission = 
                alpha * PixelRenderer.color2V3D(mapImage_.GetPixel(longitude, latitude)) + 
                (1 - alpha) * PixelRenderer.color2V3D(Color.Gray);
            return true;
        }
    }
}
